Kotlin 的策略模式沒有語法糖,所以跟 Java 的差不多
interface Promotion {
    fun getType(): String
    fun getPrice(originalPrice: BigDecimal, discount: BigDecimal, quantity: Int): BigDecimal
}
class ItemPromotion : Promotion {
    override fun getType(): String {
        return "單件折扣"
    }
    override fun getPrice(
        originalPrice: BigDecimal,
        discount: BigDecimal,
        quantity: Int
    ): BigDecimal {
        val price = originalPrice.multiply(discount)
        return price
    }
}
class SecondItemPromotion : Promotion {
    override fun getType(): String {
        return "第二個商品折扣"
    }
    override fun getPrice(
        originalPrice: BigDecimal,
        discount: BigDecimal,
        quantity: Int
    ): BigDecimal {
        var price = originalPrice.multiply(discount)
        price = price.add(originalPrice)
        return price
    }
}
class NoPromotion : Promotion {
    override fun getType(): String {
        return "沒有折扣"
    }
    override fun getPrice(
        originalPrice: BigDecimal,
        discount: BigDecimal,
        quantity: Int
    ): BigDecimal {
        val price = originalPrice.multiply(BigDecimal.valueOf(quantity.toLong()))
        return price
    }
}
getPayMoney方法寫促銷策略class Member(var name: String) {
    var promotion: Promotion? = null
    fun getPayMoney(originalPrice: BigDecimal?, discount: BigDecimal?, quantity: Int): BigDecimal {
        val money: BigDecimal
        when (quantity) {
            1 -> {
                promotion = ItemPromotion()
                money = (promotion as ItemPromotion).getPrice(originalPrice!!, discount!!, quantity)
            }
            2 -> {
                promotion = SecondItemPromotion()
                money = (promotion as SecondItemPromotion).getPrice(
                    originalPrice!!,
                    discount!!,
                    quantity
                )
            }
            else -> {
                promotion = NoPromotion()
                money = (promotion as NoPromotion).getPrice(originalPrice!!, discount!!, quantity)
            }
        }
        return money
    }
}
class KotlinTest {
    @Test
    fun show() {
        val text = StringBuilder()
        text.append("\n")
        text.append(getMemberText(Member("Andy"), 1))
        text.append("\n")
        text.append(getMemberText(Member("Jack"), 2))
        text.append("\n")
        text.append(getMemberText(Member("Rich"), 100))
        text.append("\n")
        assertEquals("測試", text.toString())
    }
    private fun getMemberText(member: Member, quantity: Int): String {
        val memberText = java.lang.StringBuilder()
        memberText.append("姓名:")
        memberText.append(member.name)
        memberText.append(" / ")
        memberText.append("付多少錢:")
        memberText.append(member.getPayMoney(BigDecimal("100"), BigDecimal("0.8"), quantity))
        memberText.append(" / ")
        memberText.append("折扣名稱:")
        member.promotion.let {
            memberText.append(it?.getType())
        }
        return memberText.toString()
    }
}
姓名:Andy / 付多少錢:80.0 / 折扣名稱:單件折扣
姓名:Jack / 付多少錢:180.0 / 折扣名稱:第二個商品折扣
姓名:Rich / 付多少錢:10000 / 折扣名稱:沒有折扣